﻿
Imports System.ComponentModel

Public Class FrmVoucherInput
    Private m_voucherList As List(Of ClsTVoucher)
    Private m_voucherDict As Dictionary(Of String, Integer) = New Dictionary(Of String, Integer)()

    Private m_curVoucher As ClsTVoucher
    Private m_curVoucherIndex As Integer
    Private m_presaveVoucher As ClsTVoucher '要进行保存的凭证对象
    Private m_entryCount As Integer '当前处理的凭证的分录行数

    Private m_curEntry As Int16 '当前处于选择状态的分录行
    'Private m_voucherIndex As Int16 '当前凭证在集合中位置

    'Private m_tmpVoucherList As List(Of ClsTVoucher) '用于临时进行数据库处理

    Private m_dataGridCurrentRow As Int16 '当前表格正在处理的行

    Private m_maxVoucherId As Int32 '新建凭证的凭证编号

    Private m_sumOfCredit As Decimal '借方合计值 
    Private m_sumOfDebit As Decimal '贷方合计值 

    Private m_state As Integer '当前状态：0-浏览，1-新建，2-编辑
    Private m_dirty As Boolean
    Private m_saving As Boolean
    Private m_loading As Boolean
    '数据源
    Private m_voucherGroupList As List(Of ClsTVoucherGroup)
    Private m_employeeList As List(Of ClsTEmployee)
    Private m_AccountList As List(Of ClsTAccount)


    '窗体调用主窗体显示过程
    Private Delegate Sub SetMainShowInfo(ByVal info As String)
    Private m_showInfoInMainForm As SetMainShowInfo = New SetMainShowInfo(AddressOf SetMessageToMianForm)

    '窗体其他加载过程委托
    Private Delegate Sub LoadContinue()
    Private m_loadDone As LoadContinue = New LoadContinue(AddressOf ContinueLoadForm)

    Private Delegate Sub UpdateSumValue()
    Private m_subUpdateSumValue As UpdateSumValue = New UpdateSumValue(AddressOf UpdateCreditAndDebit)

    Private Delegate Sub SaveVoucherDone()
    Private m_saveVoucherDone As SaveVoucherDone = New SaveVoucherDone(AddressOf VoucherSaveDone)
    Private m_ifSaved As Boolean = False '是否正确保存

    Private Sub RecieveVoucherGroupChange(ByVal sender As Object, ByVal e As TransEventArg)
        '收到凭证类别变化 的通知，要修改当前窗体上的凭证类别数据源
        If e.Msg.Length < 12 Then
            Return
        End If

        Dim tmpS As String = e.Msg.Substring(e.Msg.Length - 12)
        Dim tmpAction As String = e.Msg.Substring(0, e.Msg.Length - 12)

        If Not tmpS.Equals("VoucherGroup") Then
            Return
        End If

        Dim tmpVoucherGroup As ClsTVoucherGroup = TryCast(e.Obj, ClsTVoucherGroup)

        If tmpVoucherGroup Is Nothing Then
            Return

        End If

        Select Case tmpAction
            Case "Insert"
                '加入新类别
                m_voucherGroupList.Add(tmpVoucherGroup)
            Case "Modify"
                '修改类别
                For Each tmpVG As ClsTVoucherGroup In m_voucherGroupList
                    If tmpVG.GroupId = tmpVoucherGroup.GroupId Then
                        m_voucherGroupList.Remove(tmpVG)
                        Exit For
                    End If
                Next
                m_voucherGroupList.Add(tmpVoucherGroup)
            Case "Delete"
                '删除类别
                For Each tmpVG As ClsTVoucherGroup In m_voucherGroupList
                    If tmpVG.GroupId = tmpVoucherGroup.GroupId Then
                        m_voucherGroupList.Remove(tmpVG)
                        Exit For
                    End If
                Next
        End Select
        'cmbVoucherGroup.DataSource = Nothing
        'cmbVoucherGroup.DataSource = m_voucherGroupList
        InitialVoucherGroupDataSource()
    End Sub

    Private Sub RecieveEmployeeChange(ByVal sender As Object, ByVal e As TransEventArg)
        '收到员工信息变化 的通知,要修改当前窗口的员工数据源
        If Not e.Msg.Equals("InsertEmployee") AndAlso e.Msg.Equals("ModifyEmployee") Then
            Return
        End If

        Dim tmpEmployee As ClsTEmployee = TryCast(e.Obj, ClsTEmployee)
        If e.Msg.Equals("InsertEmployee") AndAlso tmpEmployee IsNot Nothing Then
            '加入到数据源
            m_employeeList.Add(tmpEmployee)
        Else
            '修改数据源
            For Each tmpE As ClsTEmployee In m_employeeList
                If tmpE.EmployeeId = tmpEmployee.EmployeeId Then
                    tmpE.EmployeeName = tmpEmployee.EmployeeName
                    tmpE.DepartmentName = tmpEmployee.DepartmentName
                    tmpE.DepartmentId = tmpEmployee.DepartmentId
                    tmpE.Contact = tmpEmployee.Contact

                    Exit For
                End If
            Next
        End If

        InitialEmployeeHanderDataSource()
    End Sub

    Private Sub RecieveAccountChange(ByVal sender As Object, ByVal e As TransEventArg)
        '收到科目信息变化 的通知，要修改当前窗体上的科目数据源
        If e.Msg.Length < 7 Then
            Return
        End If

        Dim tmpS As String = e.Msg.Substring(e.Msg.Length - 7)
        Dim tmpAction As String = e.Msg.Substring(0, e.Msg.Length - 7)

        If Not tmpS.Equals("Account") Then
            Return
        End If

        Dim tmpTAcct As ClsTAccount = TryCast(e.Obj, ClsTAccount)

        If tmpTAcct Is Nothing Then
            Return

        End If

        Dim acctIndex As Integer '当前科目在集合中的索引 = FindAcctIndex(tmpTAcct.AccountCode)

        Select Case tmpAction
            Case "Insert"
                '加入新科目
                If tmpTAcct.Level = 1 Then
                    '一级科目，插入到第一个位置
                    m_AccountList.Insert(0, tmpTAcct)
                Else
                    '取出其父科目的索引
                    Dim parentIndex As Integer = FindAcctIndex(tmpTAcct.PrevLevelCode)
                    If parentIndex = -1 Then
                        '没找到，插入到第一个位置
                        m_AccountList.Insert(0, tmpTAcct)
                    Else
                        '如果找到父科目，则说明父科目此时应从集合中移除
                        m_AccountList.Remove(m_AccountList.Item(parentIndex))
                        '插入到父科目位置
                        m_AccountList.Insert(parentIndex, tmpTAcct)
                    End If
                End If

            Case "Modify"
                '找出自身索引
                acctIndex = FindAcctIndex(tmpTAcct.AccountCode)
                If acctIndex <> -1 Then
                    '该科目在集合列表中，要查看此时科目是否为末级，如果不是，则需要从集合列表中移除
                    If tmpTAcct.IfLastLevel Then
                        '是末级，则修改
                        m_AccountList.Item(acctIndex) = tmpTAcct
                    Else
                        '不是末级，移除
                        m_AccountList.RemoveAt(acctIndex)
                    End If
                Else
                    '没找到，
                    If tmpTAcct.IfLastLevel Then
                        '说明是非末级修改为末级，需要加入到科目集合中
                        '说明马上要使用，加到第一个位置
                        '不是末级，则不用处理
                        m_AccountList.Insert(0, tmpTAcct)
                    End If
                End If

            Case "Delete"
                '删除
                '找出在集合中的索引，
                acctIndex = FindAcctIndex(tmpTAcct.AccountCode)
                If acctIndex <> -1 Then
                    '不在集合中，说明不是末级科目
                    '如果在集合中，则需要移除
                    m_AccountList.RemoveAt(acctIndex)
                End If
        End Select

        InitialAccountDataSource()
    End Sub

    Private Sub DisableAllControl()

        '凭证打印区
        btnPaperSetup.Enabled = False
        btnPreview.Enabled = False
        btnPrint.Enabled = False

        '前进后退按钮
        btnFirst.Enabled = False
        btnPrev.Enabled = False
        btnNext.Enabled = False
        btnLast.Enabled = False

        '科目区
        btnFindAcct.Enabled = False
        btnAcctSetup.Enabled = False

        '分录编辑区
        btnDeleteEntry.Enabled = False
        btnDebitToCredit.Enabled = False
        btnAcctBalance.Enabled = False

        '凭证编辑区
        btnSave.Enabled = False
        btnCancel.Enabled = False

        btnAddVoucher.Enabled = False
        btnCopyVoucher.Enabled = False
        btnDeleteVoucher.Enabled = False
        btnModifyVoucher.Enabled = False
        btnFindVoucher.Enabled = False

        '凭证审核区
        btnCheck.Enabled = False
        btnCheckAll.Enabled = False
        btnUnCheckAll.Enabled = False

        '凭证类别和员工管理区
        btnVoucherGroup.Enabled = False
        btnEmployee.Enabled = False

        dgvVoucher.Enabled = False

    End Sub

    Private Sub FrmVoucherInput_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        '设置事件订阅
        AddHandler ClsBroker.OnChange, AddressOf RecieveEmployeeChange
        AddHandler ClsBroker.OnChange, AddressOf RecieveVoucherGroupChange
        AddHandler ClsBroker.OnChange, AddressOf RecieveAccountChange

        m_loading = True

        '禁止按钮等控件
        DisableAllControl()

        '设置录入表格
        InitialDataGridView()
        '设置控件数据源
        InitialDataSource()
        '设置控件组位置
        Me.groupOther.Left = Me.groupQuantity.Left
        Me.groupOther.Top = Me.groupQuantity.Top
        Me.groupOther.Visible = False
        '取消表格选区
        Me.dgvVoucher.CurrentCell = Nothing
        '载入数据
        LoadData()

    End Sub

    Private Sub InitialVoucherGroupDataSource()

        '凭证类别
        If m_voucherGroupList Is Nothing Then
            Dim tmpVoucherGroupDb As ClsTVoucherGroupDbAccess = New ClsTVoucherGroupDbAccess(sysUserDataConnectionString)
            m_voucherGroupList = tmpVoucherGroupDb.GetAllRecords(Of ClsTVoucherGroup)()
        End If

        Me.cmbVoucherGroup.DataSource = Nothing

        Me.cmbVoucherGroup.DataSource = m_voucherGroupList
        Me.cmbVoucherGroup.ValueMember = "ShortName"
        Me.cmbVoucherGroup.DisplayMember = "ShortName"
        Me.cmbVoucherGroup.SelectedIndex = -1
    End Sub


    Private Sub InitialEmployeeHanderDataSource()
        '员工
        If m_employeeList Is Nothing Then
            Dim tmpEmployeeDb As ClsTEmployeeDbAccess = New ClsTEmployeeDbAccess(sysUserDataConnectionString)
            m_employeeList = tmpEmployeeDb.GetAllRecords(Of ClsTEmployee)()
        End If

        Me.cmbCahser.DataSource = Nothing

        Me.cmbCahser.DataSource = m_employeeList
        Me.cmbCahser.DisplayMember = "EmployeeName"
        Me.cmbCahser.ValueMember = "EmployeeName"
        Me.cmbCahser.SelectedIndex = -1

        Me.cmbHander.DataSource = Nothing

        Me.cmbHander.DataSource = m_employeeList
        Me.cmbHander.DisplayMember = "EmployeeName"
        Me.cmbHander.ValueMember = "EmployeeName"
        Me.cmbHander.SelectedIndex = -1

    End Sub

    Private Sub InitialAccountDataSource()
        '会计科目
        If m_AccountList Is Nothing Then
            Dim tmpAcctDb As ClsTAccountDbAccess = New ClsTAccountDbAccess(sysUserDataConnectionString)
            m_AccountList = tmpAcctDb.GetAllLastAccount()
        End If

        Dim tmpColumn As DataGridViewMultiColumnComboBoxColumn = CType(Me.dgvVoucher.Columns(1), DataGridViewMultiColumnComboBoxColumn)

        tmpColumn.DataSource = Nothing

        tmpColumn.DataSource = m_AccountList
        tmpColumn.SelectedIndex2 = 5 '科目全名
        tmpColumn.DisplayMember = "AccountCode"
        tmpColumn.ValueMember = "AccountCode"
        tmpColumn.SelectedIndex = -1

    End Sub


    Private Sub InitialDataSource()
        '凭证类别
        InitialVoucherGroupDataSource()

        '员工 经手人与出纳
        InitialEmployeeHanderDataSource()

        '会计科目
        InitialAccountDataSource()

    End Sub

    ''' <summary>
    ''' 对控件内容进行数据验证
    ''' </summary>
    ''' <returns>True是符合保存条件</returns>
    Private Function ValidedControlContent() As Boolean

        '第一步，检查凭证主体信息是否符合条件
        '1、凭证的必填写信息
        '凭证组别以及组别中的号码
        If Me.cmbVoucherGroup.SelectedIndex = -1 Then
            '错误，必须 选择凭证所属组别
            MessageBox.Show("必须选择当前凭证所在组别。", "凭证保存检查")
            Return False
        End If
        '判断借方和贷方数据是否一致
        Dim tmpCredit As Decimal
        Dim tmpDebit As Decimal
        Decimal.TryParse(Me.txtSumOfDebit.Text, tmpCredit)
        Decimal.TryParse(Me.txtSumOfCredit.Text, tmpDebit)
        If tmpCredit <> tmpDebit Then
            MessageBox.Show("借贷不平衡，请修改后保存。", "凭证保存检查")
            Return False
        End If
        '第二步，检查各行分录内容
        '先删除不符合最基本条件的行
        Dim tmpAddNum As Int16 = 0
        Dim tmpEntryNum As Int16 = 0
        '为避免新行未提交出错，先提交编辑
        Me.dgvVoucher.EndEdit()
        '
        For Each tmpR As DataGridViewRow In Me.dgvVoucher.Rows
            '先进行初步检查
            '到这里说明借贷平衡，那如果不包含科目就表明没有必要存在
            If tmpR.Cells(1).Value Is Nothing Then
                Me.dgvVoucher.Rows.Remove(tmpR)
                tmpAddNum += 1
            Else
                tmpEntryNum += 1
            End If
            'If Not ValidateRow(tmpR.Index) Then
            '    '不符合要求则删除整行
            '    Me.dgvVoucher.Rows.Remove(tmpR)
            '    '等增加行数
            '    tmpAddNum += 1
            'Else
            '    tmpEntryNum += 1
            'End If
        Next
        If tmpAddNum > 0 Then
            Me.dgvVoucher.Rows.Add(tmpAddNum)
        End If
        '对所有行符合条件进行内容检查
        '分录不能少于2行
        If tmpEntryNum < 2 Then
            MessageBox.Show("当前凭证分录不符合保存条件，请修改后保存。", "凭证保存检查")

            Return False
        End If
        '对分录进行内容检查
        Dim tmpRow As DataGridViewRow
        Dim tmpOk As Boolean = True
        Dim tmpC As Decimal = 0
        Dim tmpSumOfC As Decimal = 0
        Dim tmpD As Decimal = 0
        Dim tmpSumOfD As Decimal = 0

        For i As Integer = 0 To tmpEntryNum - 1
            tmpRow = Me.dgvVoucher.Rows(i)
            '检查摘要
            If tmpRow.Cells(0).Value Is Nothing Then
                MessageBox.Show("第" & i + 1 & "行分录没有摘要，请输入。", "凭证保存检查")
                tmpOk = False
                Exit For
            End If
            '检查科目
            If tmpRow.Cells(1).Value Is Nothing Then
                MessageBox.Show("第" & i + 1 & "行分录没有选择科目，请修改。", "凭证保存检查")
                tmpOk = False
                Exit For
            End If
            '如果科目名称没有，则进行填写
            If tmpRow.Cells(2).Value Is Nothing Then
                '取出科目集合中相应内容
                tmpRow.Cells(2).Value = m_AccountList.Item(FindAcctIndex(tmpRow.Cells(1).Value.ToString)).AccountName
            End If
            '取出借贷金额，进行比对
            Decimal.TryParse(tmpRow.Cells(3).Value, tmpC) ' 借方金额
            tmpSumOfC += tmpC
            Decimal.TryParse(tmpRow.Cells(4).Value, tmpD) '贷方金额
            tmpSumOfD += tmpD
            '判断同一行借贷是否都有非0值 
            If tmpC <> 0 AndAlso tmpD <> 0 Then
                MessageBox.Show("第" & i + 1 & "行分录借贷方同时有数据，请修改。", "凭证保存检查")
                tmpOk = False
                Exit For
            End If
        Next
        '判断是否有不符合条件分录行
        If Not tmpOk Then
            Return tmpOk
        End If


        '判断借贷是否相等
        If tmpSumOfC <> tmpSumOfD Then
            MessageBox.Show("凭证借贷合计不平衡，请修改。", "凭证保存检查")
            tmpOk = False
        End If

        '检查当下凭证合计是否需要修改
        If m_sumOfCredit <> tmpSumOfC OrElse m_sumOfDebit <> tmpSumOfD Then
            m_sumOfCredit = tmpSumOfC
            m_sumOfDebit = tmpSumOfD
            '修改凭证合计
            UpdateCreditAndDebit()
        End If

        '保存分录总行数
        m_entryCount = tmpEntryNum

        '
        Return tmpOk
    End Function

    ''' <summary>
    ''' 根据指定的科目编码返回科目集合中相应的科目对象的索引
    ''' </summary>
    ''' <param name="acctCode">要检查的科目编码</param>
    ''' <returns>科目名称</returns>
    Private Function FindAcctIndex(ByVal acctCode As String) As Integer
        Dim tmpIndex As Integer = -1

        If String.IsNullOrEmpty(acctCode) Then
            Return tmpIndex
        End If

        For i As Integer = 0 To m_AccountList.Count - 1
            If m_AccountList.Item(i).AccountCode.Equals(acctCode) Then
                tmpIndex = i
                Exit For
            End If
        Next

        Return tmpIndex
    End Function

    ''' <summary>
    ''' 将当前控件修改的内容赋值给当前凭证处理对象m_curVoucher
    ''' </summary>
    Private Sub ControlToClass()
        '在赋值前需要进行数据验证
        m_presaveVoucher = New ClsTVoucher()

        With m_presaveVoucher
            '判断是新增还是编辑
            If m_state = 1 Then
                .VoucherAutoId = 0 '这个要等保存成功后再修改成实际值
            Else
                .VoucherAutoId = m_curVoucher.VoucherAutoId
            End If
            .VoucherId = Me.txtVoucherId.Text
            .WorkPeriod = sysCurrentLedgerSetting.LedgerWorkYear
            .VoucherGroupId = Me.txtVoucherGroupId.Text
            .VoucherGroup = Me.cmbVoucherGroup.SelectedValue
            .VoucherNumber = Me.txtVoucherNumber.Text
            .VoucherDate = Me.dtpVoucherDate.Value
            If Me.txtAttachment.Text = "" Then
                .Attachment = 0
            Else
                .Attachment = Integer.Parse(Me.txtAttachment.Text.Trim())
            End If
            '.Attachment = IIf(Me.txtAttachment.Text = "", 0, Integer.Parse(Me.txtAttachment.Text.Trim()))
            If Me.cmbCahser.SelectedIndex = -1 Then
                .Casher = ""
            Else
                .Casher = Me.cmbCahser.SelectedValue
            End If

            .Checked = False
            .Checker = ""

            .Posted = False
            .Poster = ""

            .Maker = sysCurrentClsUser.UserName

            If Me.cmbHander.SelectedIndex = -1 Then
                .Hander = ""
            Else
                .Hander = Me.cmbHander.SelectedValue
            End If

            .SumOfCredit = m_sumOfCredit
            .SumOfDebit = m_sumOfDebit

            If m_state = 1 Then

                .VoucherStatus = "正常"
            Else
                .VoucherStatus = m_curVoucher.VoucherStatus
            End If

            .Posted = False '过账的不能编辑
            If m_state = 1 Then

                .Module = "普通"
            Else
                .Module = m_curVoucher.Module
            End If

            .Deleted = False '删除的也不能显示及编辑

            .Memo = IIf(Me.txtMemo.Text.Trim() = "", "", Me.txtMemo.Text.Trim())
            .MoneyHz = Me.lblMoneyHZ.Text

            .EntryList = New List(Of ClsTVoucherDetail)()
        End With
        '凭证分录
        Dim tmpEntry As ClsTVoucherDetail
        For i As Integer = 0 To m_entryCount - 1
            tmpEntry = New ClsTVoucherDetail()
            With tmpEntry
                .DetailId = 0
                .VoucherId = m_presaveVoucher.VoucherAutoId '这个要等保存成功后全部修改成实际的
                .VoucherGroupId = Me.txtVoucherGroupId.Text
                .VoucherGroup = Me.cmbVoucherGroup.SelectedValue
                .VoucherNumber = Me.txtVoucherNumber.Text
                .EntryNumber = i
                .Excerpta = Me.dgvVoucher.Rows(i).Cells(0).Value.ToString().Trim
                .AccountCode = Me.dgvVoucher.Rows(i).Cells(1).Value.ToString()
                .AccountCodeName = Me.dgvVoucher.Rows(i).Cells(2).Value.ToString()
                Decimal.TryParse(Me.dgvVoucher.Rows(i).Cells(3).Value, .Debit) '借方
                Decimal.TryParse(Me.dgvVoucher.Rows(i).Cells(4).Value, .Credit) '贷方
                Single.TryParse(Me.dgvVoucher.Rows(i).Cells(5).Value, .Quantity) '数量
                Decimal.TryParse(Me.dgvVoucher.Rows(i).Cells(6).Value, .Price) '单价
                If Me.dgvVoucher.Rows(i).Cells(7).Value Is Nothing Then '单位
                    .Unit = ""
                Else
                    .Unit = Me.dgvVoucher.Rows(i).Cells(7).Value.ToString()
                End If

                If Me.dgvVoucher.Rows(i).Cells(8).Value Is Nothing Then  '结算方式
                    .SettleMode = ""
                Else
                    .SettleMode = Me.dgvVoucher.Rows(i).Cells(8).Value.ToString()
                End If

                If Me.dgvVoucher.Rows(i).Cells(9).Value Is Nothing Then
                    .SettleCode = ""
                Else
                    .SettleCode = Me.dgvVoucher.Rows(i).Cells(9).Value.ToString()  '结算代码
                End If
                '结算日期
                If Me.dgvVoucher.Rows(i).Cells(10).Value Is Nothing Then
                    .SettleDate = DateTime.Now()
                Else
                    .SettleDate = DateTime.Parse(Me.dgvVoucher.Rows(i).Cells(10).Value.ToString())
                End If
                .Payer = "" '此字段不使用
                '外币代码
                If Me.dgvVoucher.Rows(i).Cells(11).Value Is Nothing Then
                    .CurrencyCode = ""
                Else
                    .CurrencyCode = Me.dgvVoucher.Rows(i).Cells(11).Value.ToString()
                End If
                Single.TryParse(Me.dgvVoucher.Rows(i).Cells(12).Value, .ExchangeRate) '外币汇率
                Decimal.TryParse(Me.dgvVoucher.Rows(i).Cells(13).Value, .CurrencyNumber) '外币数量
                '业务编号
                If Me.dgvVoucher.Rows(i).Cells(14).Value Is Nothing Then
                    .TransCode = ""
                Else
                    .TransCode = Me.dgvVoucher.Rows(i).Cells(14).Value.ToString()
                End If
                '项目代码
                If Me.dgvVoucher.Rows(i).Cells(15).Value Is Nothing Then
                    .ProjectCode = ""
                Else
                    .ProjectCode = Me.dgvVoucher.Rows(i).Cells(15).Value.ToString()
                End If
                '项目名称
                If Me.dgvVoucher.Rows(i).Cells(16).Value Is Nothing Then
                    .ProjectName = ""
                Else
                    .ProjectName = Me.dgvVoucher.Rows(i).Cells(16).Value.ToString()
                End If
                '往来单位
                If Me.dgvVoucher.Rows(i).Cells(17).Value Is Nothing Then
                    .ProjectCustomer = ""
                Else
                    .ProjectCustomer = Me.dgvVoucher.Rows(i).Cells(17).Value.ToString()
                End If
            End With
            '添加到凭证的分录集合列表中
            m_presaveVoucher.EntryList.Add(tmpEntry)
        Next
    End Sub

    ''' <summary>
    ''' 将当前处理的凭证对象m_curVoucher赋值给控件
    ''' </summary>
    Private Sub ClassToControl()
        If m_curVoucher Is Nothing Then
            Return
        End If
        Try

            '将当前处理的凭证加载到窗体控件
            '第一，加载主凭证信息
            With m_curVoucher

                Me.txtVoucherId.Text = .VoucherId '01
                Me.txtVoucherGroupId.Text = .VoucherGroupId
                Me.cmbVoucherGroup.SelectedValue = .VoucherGroup
                Me.txtVoucherNumber.Text = .VoucherNumber
                Me.dtpVoucherDate.Value = .VoucherDate
                Me.txtAttachment.Text = IIf(.Attachment = 0, "", .Attachment)
                Me.cmbCahser.SelectedValue = .Casher
                Me.cmbHander.SelectedValue = .Hander
                Me.lblPoster.Text = .Poster
                Me.lblMaker.Text = .Maker
                Me.lblChecker.Text = .Checker
                Me.txtSumOfDebit.Text = .SumOfDebit.ToString("#,###.00") '借方
                Me.txtSumOfCredit.Text = .SumOfCredit.ToString("#,###.00") '贷方
                Me.lblVoucherStatus.Visible = IIf(.VoucherStatus.Equals("红冲"), True, False)
                Me.lblVoucherStatus.Visible = .Posted
                Me.lblMoneyHZ.Text = .MoneyHz
                '是否红冲
                If .VoucherStatus = "红冲" Then
                    Me.lblVoucherStatus.Visible = True
                Else
                    Me.lblVoucherStatus.Visible = False
                End If
                '是否审核
                If .Checked Then
                    Me.lblIfChecked.Visible = True
                Else
                    Me.lblIfChecked.Visible = False
                End If
                '是否过账
                If .Posted Then
                    Me.lblIfPosted.Visible = True
                Else
                    Me.lblIfPosted.Visible = False
                End If
            End With
            '第二，加载凭证分录信息
            '清空表格内容行
            Me.dgvVoucher.Rows.Clear()
            '循环加入各行数据
            For Each tmpEntry As ClsTVoucherDetail In m_curVoucher.EntryList
                AddOneEntryToGrid(tmpEntry)
            Next

        Catch ex As Exception

        End Try
    End Sub

    ''' <summary>
    ''' 加载一行分录到表格中
    ''' </summary>
    ''' <param name="clsVD"></param>
    Private Sub AddOneEntryToGrid(ByVal clsVD As ClsTVoucherDetail)
        If clsVD Is Nothing Then
            Return
        End If

        Dim rowIndex As Integer = Me.dgvVoucher.Rows.Add()
        Dim tmpRow As DataGridViewRow = dgvVoucher.Rows.Item(rowIndex)
        tmpRow.Cells(0).Value = clsVD.Excerpta '摘要
        tmpRow.Cells(1).Value = clsVD.AccountCode '科目编码
        tmpRow.Cells(2).Value = clsVD.AccountCodeName
        tmpRow.Cells(3).Value = clsVD.Credit
        tmpRow.Cells(4).Value = clsVD.Debit
        tmpRow.Cells(5).Value = clsVD.Quantity  '数量 'single
        tmpRow.Cells(6).Value = clsVD.Price '单价 'decimal
        tmpRow.Cells(7).Value = clsVD.Unit  '单位 '单位
        tmpRow.Cells(8).Value = clsVD.SettleMode    '结算方式
        tmpRow.Cells(9).Value = clsVD.SettleCode    '结算代码
        tmpRow.Cells(10).Value = clsVD.SettleDate   '结算日期
        'tmpRow.Cells(11).Value = clsVD.Payer	此字段不使用
        tmpRow.Cells(11).Value = clsVD.CurrencyCode '外币代码
        tmpRow.Cells(12).Value = clsVD.ExchangeRate '外币汇率 'single
        tmpRow.Cells(13).Value = clsVD.CurrencyNumber   '外币数量 'decimal
        tmpRow.Cells(14).Value = clsVD.TransCode    '业务编号
        tmpRow.Cells(15).Value = clsVD.ProjectName  '项目代码
        tmpRow.Cells(16).Value = clsVD.ProjectCode  '项目名称
        tmpRow.Cells(17).Value = clsVD.ProjectCustomer  '往来单位

    End Sub

    ''' <summary>
    ''' 检查当前窗体的所有控件状态，并根据当前编辑状态进行修改
    ''' </summary>
    Private Sub CheckControlState()
        CheckContentControlState()
        CheckButtonControlState()
    End Sub

    ''' <summary>
    ''' 检查当前有内容控件的状态，根据当前状态修改内容
    ''' </summary>
    Private Sub CheckContentControlState()
        Me.txtVoucherNumber.ReadOnly = True
        Me.txtSumOfCredit.ReadOnly = True
        Me.txtSumOfDebit.ReadOnly = True
        Select Case m_state
            Case 0 '浏览
                '如果有当前正在处理的则把当前凭证内容放入控件
                '将当前处理的凭证对象设置给控件
                ClassToControl()
                '当前内容不能修改
                '凭证主信息
                Me.txtVoucherId.ReadOnly = True
                Me.txtVoucherGroupId.ReadOnly = True
                If m_voucherList.Count > 0 Then
                    Me.cmbVoucherGroup.Enabled = True '可用，用来跳转凭证
                    Me.txtVoucherNumber.ReadOnly = False '可用，用来跳转凭证
                Else
                    Me.cmbVoucherGroup.Enabled = False  '没有内容，则不可用，用来跳转凭证
                    Me.txtVoucherNumber.ReadOnly = True  '没有内容，则可用，用来跳转凭证
                End If
                'Me.cmbVoucherGroup.SelectedIndex = -1
                Me.dtpVoucherDate.Enabled = False
                Me.txtAttachment.ReadOnly = True
                Me.cmbCahser.Enabled = False
                Me.cmbHander.Enabled = False
                '设置表格不可编辑
                'Me.dgvVoucher.AllowUserToAddRows = False
                Me.dgvVoucher.InEidtMode = False
                Me.dgvVoucher.ReadOnly = True
                '凭证分录情况在datagridview某行获得焦点时设置

            Case 1 '新增
                '凭证主信息
                Me.txtVoucherId.ReadOnly = False
                Me.txtVoucherGroupId.ReadOnly = False
                Me.cmbVoucherGroup.Enabled = True
                Me.dtpVoucherDate.Enabled = True
                Me.txtAttachment.ReadOnly = False
                Me.cmbCahser.Enabled = True
                Me.cmbHander.Enabled = True
                Me.txtVoucherNumber.ReadOnly = True
                '设置表格可编辑
                'Me.dgvVoucher.AllowUserToAddRows = True
                Me.dgvVoucher.InEidtMode = True
                Me.dgvVoucher.ReadOnly = False
                '新建一个新凭证对象时修改控件内容
                NewContentToControl()
            Case 2 '修改
                Me.txtVoucherId.ReadOnly = False
                Me.txtVoucherGroupId.ReadOnly = False
                Me.cmbVoucherGroup.Enabled = True
                Me.dtpVoucherDate.Enabled = True
                Me.txtAttachment.ReadOnly = False
                Me.cmbCahser.Enabled = True
                Me.cmbHander.Enabled = True

                '设置表格可编辑
                'Me.dgvVoucher.AllowUserToAddRows = True
                Me.dgvVoucher.InEidtMode = True
                Me.dgvVoucher.ReadOnly = False

        End Select

    End Sub

    ''' <summary>
    ''' 为新建凭证准备控件内容
    ''' </summary>
    Private Sub NewContentToControl()
        Me.dgvVoucher.Rows.Clear()

        Me.dgvVoucher.Rows.Add(6)

        'Me.cmbVoucherGroup.Select()
        Me.cmbVoucherGroup.SelectedIndex = -1
        Me.cmbHander.SelectedIndex = -1
        Me.cmbCahser.SelectedIndex = -1

        Me.txtVoucherId.Text = ""
        Me.txtVoucherGroupId.Text = ""
        Me.txtVoucherNumber.Text = ""
        Me.txtAttachment.Text = "0"

        Me.cmbVoucherGroup.Focus()

    End Sub

    ''' <summary>
    ''' 根据当前编辑状态修改各按钮的状态
    ''' </summary>
    Private Sub CheckButtonControlState()

        Dim haveVoucher As Boolean = m_voucherList.Count > 0

        Select Case m_state
            Case 0 '浏览

                '凭证打印区
                btnPaperSetup.Enabled = haveVoucher
                btnPreview.Enabled = haveVoucher  'm_curVoucher IsNot Nothing
                btnPrint.Enabled = haveVoucher 'btnPreview.Enabled

                '前进后退按钮
                btnFirst.Enabled = m_curVoucherIndex > 0
                btnPrev.Enabled = m_curVoucherIndex > 0
                btnNext.Enabled = m_curVoucherIndex < m_voucherList.Count - 1
                btnLast.Enabled = m_curVoucherIndex < m_voucherList.Count - 1

                '科目区
                btnFindAcct.Enabled = m_state > 0
                btnAcctSetup.Enabled = m_state > 0

                '分录编辑区
                btnDeleteEntry.Enabled = False
                btnDebitToCredit.Enabled = False
                btnAcctBalance.Enabled = False


                '凭证编辑区
                btnSave.Enabled = False
                btnCancel.Enabled = False '撤消修改或新建

                btnAddVoucher.Enabled = True
                btnCopyVoucher.Enabled = True
                btnDeleteVoucher.Enabled = haveVoucher
                btnModifyVoucher.Enabled = haveVoucher
                btnFindVoucher.Enabled = haveVoucher
                If m_curVoucher IsNot Nothing Then
                    If m_curVoucher.Posted Or m_curVoucher.Checked Then
                        '过账的凭证不能修改、删除
                        '已审核的不能删除和修改
                        btnModifyVoucher.Enabled = False
                        btnDeleteVoucher.Enabled = False
                    End If
                End If

                '凭证审核区
                btnCheck.Enabled = haveVoucher
                btnCheckAll.Enabled = haveVoucher
                btnUnCheckAll.Enabled = haveVoucher

                '凭证类别和员工管理区
                btnVoucherGroup.Enabled = False
                btnEmployee.Enabled = False

                '关闭退出
                'btnClose.Enabled = True


            Case 1 '新建

                '凭证打印区
                btnPaperSetup.Enabled = False
                btnPreview.Enabled = False
                btnPrint.Enabled = False

                '前进后退按钮
                btnFirst.Enabled = False
                btnPrev.Enabled = False
                btnNext.Enabled = False
                btnLast.Enabled = False

                '科目区
                btnFindAcct.Enabled = True
                btnAcctSetup.Enabled = True

                '分录编辑区
                btnDeleteEntry.Enabled = True
                btnDebitToCredit.Enabled = True
                btnAcctBalance.Enabled = True

                '凭证编辑区
                btnSave.Enabled = True
                btnCancel.Enabled = True

                btnAddVoucher.Enabled = False
                btnCopyVoucher.Enabled = True
                btnDeleteVoucher.Enabled = False
                btnModifyVoucher.Enabled = False
                btnFindVoucher.Enabled = False

                '凭证审核区
                btnCheck.Enabled = False
                btnCheckAll.Enabled = False
                btnUnCheckAll.Enabled = False

                '凭证类别和员工管理区
                btnVoucherGroup.Enabled = True
                btnEmployee.Enabled = True

                '退出
                'btnClose.Enabled = True

            Case 2 '修改

                '凭证打印区
                btnPaperSetup.Enabled = False
                btnPreview.Enabled = False
                btnPrint.Enabled = False

                '前进后退按钮
                btnFirst.Enabled = False
                btnPrev.Enabled = False
                btnNext.Enabled = False
                btnLast.Enabled = False

                '科目区
                btnFindAcct.Enabled = True
                btnAcctSetup.Enabled = True

                '分录编辑区
                btnDeleteEntry.Enabled = True
                btnDebitToCredit.Enabled = True
                btnAcctBalance.Enabled = True

                '凭证编辑区
                btnSave.Enabled = True
                btnCancel.Enabled = True

                btnAddVoucher.Enabled = False
                btnCopyVoucher.Enabled = True
                btnDeleteVoucher.Enabled = False
                btnModifyVoucher.Enabled = False
                btnFindVoucher.Enabled = False

                '凭证审核区
                btnCheck.Enabled = False
                btnCheckAll.Enabled = False
                btnUnCheckAll.Enabled = False

                '凭证类别和员工管理区
                btnVoucherGroup.Enabled = True
                btnEmployee.Enabled = True

                '退出
                'btnClose.Enabled = True

        End Select
    End Sub

    ''' <summary>
    ''' 加载凭证数据
    ''' </summary>
    Private Sub LoadData()
        m_loading = True

        sysFrmMdiMain.SetNotifyText("正在加载凭证数据，请稍候...")
        Dim t As Threading.Thread = New Threading.Thread(AddressOf LoadAcctFromDb)
        t.Start()
    End Sub


    ''' <summary>
    ''' 在MDI主窗体上显示信息
    ''' </summary>
    ''' <param name="info"></param>
    Private Sub SetMessageToMianForm(ByVal info As String)
        sysFrmMdiMain.SetNotifyText(info)
    End Sub


    ''' <summary>
    ''' 载入当前期间的所有凭证，
    ''' </summary>
    Private Sub LoadAcctFromDb()
        'Dim tmpBeginTime As DateTime = Now()
        'Debug.Print("开始：" & tmpBeginTime.ToLongTimeString)


        Dim tmpVoucherDb As ClsTVoucherDbAccess = New ClsTVoucherDbAccess(sysUserDataConnectionString)
        Dim tmpDetailDb As ClsTVoucherDetailDbAccess = New ClsTVoucherDetailDbAccess(sysUserDataConnectionString)

        m_voucherList = tmpVoucherDb.GetAllVoucherInWorkPeriod(sysCurrentLedgerSetting.LedgerWorkYear) '取出当期全部凭证主体信息

        '将凭证索引放入字典中，以备查找用
        For Each tmpVoucher As ClsTVoucher In m_voucherList
            '将每个凭证加入到字典中
            m_voucherDict.Add(tmpVoucher.VoucherGroup & tmpVoucher.VoucherNumber, m_voucherList.IndexOf(tmpVoucher))
        Next

        '取出全部分录，并加入到凭证主体信息中
        Dim tmpVDList As List(Of ClsTVoucherDetail) = New ClsTVoucherDetailDbAccess(sysUserDataConnectionString).GetAllEntriesInWorkPeriod(sysCurrentLedgerSetting.LedgerWorkYear)
        For Each tmpVD As ClsTVoucherDetail In tmpVDList
            m_voucherList(m_voucherDict(tmpVD.VoucherGroup & tmpVD.VoucherNumber)).EntryList.Add(tmpVD)
        Next

        'For Each tmpVoucher As ClsTVoucher In m_voucherList
        '    '为每一个凭证填充分录信息
        '    tmpVoucher.EntryList = tmpDetailDb.GetAllEntries(tmpVoucher.VoucherAutoId)
        '    '将每个凭证加入到字典中
        '    m_voucherDict.Add(tmpVoucher.VoucherGroup & tmpVoucher.VoucherNumber, m_voucherList.IndexOf(tmpVoucher))
        'Next

        '设置当前处理凭证
        If m_voucherList.Count > 0 Then
            m_curVoucher = m_voucherList.Item(0)
            m_curVoucherIndex = 0
        End If

        'Debug.Print("结束，共用了：" & (DateTime.Now() - tmpBeginTime).TotalSeconds & "秒")

        '调试
        sysFrmMdiMain.Invoke(m_showInfoInMainForm, New Object() {"就绪"})

        '启动其余加载
        Me.Invoke(m_loadDone)
    End Sub

    ''' <summary>
    ''' 线程加载数据后续任务
    ''' </summary>
    Private Sub ContinueLoadForm()
        '根据当前数据情况设置当前状态
        m_loading = False
        '设置当前编辑状态
        m_state = 0 '浏览
        m_saving = False
        m_dirty = False
        '设置控件状态
        CheckControlState()
        '设置科目查找窗体的数据
        'm_findAcctPopWin = New ToolStripDropDown()

        '填充弹窗
        'Dim ctlHost As ToolStripControlHost = New ToolStripControlHost(Me.groupFindAcct)
        'm_findAcctPopWin.Items.Add(ctlHost)
    End Sub

    ''' <summary>
    ''' 弹出窗体关闭事件 - 回调
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub AcctFindResult(sender As Object, e As FindAcctEventArg)
        '判断是否搜索成功
        If e.FindOk Then

            If dgvVoucher.CurrentCell.ColumnIndex = 1 Then
                '判断是否在科目编码列
                Dim row As Integer = dgvVoucher.CurrentCell.RowIndex
                Dim col As Integer = dgvVoucher.CurrentCell.ColumnIndex

                dgvVoucher.CurrentCell = dgvVoucher.Rows(row).Cells(col + 2)
                dgvVoucher.Focus()
                dgvVoucher.Rows(row).Cells(col).Value = e.AcctCode
                dgvVoucher.Rows(row).Cells(col + 1).Value = e.AcctName

            End If
        End If


    End Sub

    Private Sub ShowFindAcctWindow()

        Dim m_findAcctControl As AcctFindPopWin = New AcctFindPopWin()

        '设置列表
        'LoadAcctToListView()
        m_findAcctControl.AcctList = m_AccountList
        m_findAcctControl.AcctFindResultCallBack = AddressOf AcctFindResult
        'm_findAcctControl.LoadAcctToListView()
        Dim p As Point = New Point(0, 0)
        p.X = Me.Width / 2 - m_findAcctControl.Width / 2
        p.Y = Me.Height / 2 - m_findAcctControl.Height / 2
        Dim frmP As Point = PointToScreen(p)
        m_findAcctControl.SetDesktopLocation(frmP.X, frmP.Y)
        '显示弹窗
        m_findAcctControl.Show()

    End Sub

    ''' <summary>
    ''' 初始化分录表格
    ''' </summary>
    Private Sub InitialDataGridView()
        '初始化标题
        Dim col1 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col1.HeaderText = "摘要"
        col1.Width = 240
        Me.dgvVoucher.Columns.Add(col1)

        Dim col2 As DataGridViewMultiColumnComboBoxColumn = New DataGridViewMultiColumnComboBoxColumn()
        col2.HeaderText = "科目编码"
        col2.Width = 112
        col2.DropDownWidth = 240
        col2.AutoComplete = True
        col2.ColumnWidths = "100;0;0;120"
        Me.dgvVoucher.Columns.Add(col2)
        DataGridViewMultiColumnComboBoxColumn.DelegateCallBack = New DataGridViewMultiColumnComboBoxColumn.HotKeyCallBack(AddressOf ShowFindAcctWindow)

        Dim col3 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col3.HeaderText = "科目名称"
        col3.Width = 140
        col3.ReadOnly = True
        Me.dgvVoucher.Columns.Add(col3)

        Dim col4 As DataGridViewCurrencyTextBoxColumn = New DataGridViewCurrencyTextBoxColumn()
        col4.HeaderText = "借方"
        col4.Width = 100
        Me.dgvVoucher.Columns.Add(col4)

        Dim col5 As DataGridViewCurrencyTextBoxColumn = New DataGridViewCurrencyTextBoxColumn()
        col5.HeaderText = "贷方"
        col5.Width = 100
        Me.dgvVoucher.Columns.Add(col5)

        Dim col6 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col6.HeaderText = "数量" 'single
        col6.Visible = False
        Me.dgvVoucher.Columns.Add(col6)

        Dim col7 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col7.HeaderText = "单价" 'decimal
        col7.Visible = False
        Me.dgvVoucher.Columns.Add(col7)

        Dim col8 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col8.HeaderText = "单位" '单位
        col8.Visible = False
        Me.dgvVoucher.Columns.Add(col8)

        Dim col9 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col9.HeaderText = "结算方式"
        col9.Visible = False
        Me.dgvVoucher.Columns.Add(col9)

        Dim col10 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col10.HeaderText = "结算代码"
        col10.Visible = False
        Me.dgvVoucher.Columns.Add(col10)

        Dim col11 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col11.HeaderText = "结算日期"
        col11.Visible = False
        Me.dgvVoucher.Columns.Add(col11)

        Dim col12 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col12.HeaderText = "外币代码"
        col12.Visible = False
        Me.dgvVoucher.Columns.Add(col12)

        '.Payer = "" '此字段不使用

        Dim col13 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col13.HeaderText = "外币汇率" 'single
        col13.Visible = False
        Me.dgvVoucher.Columns.Add(col13)

        Dim col14 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col14.HeaderText = "外币数量" 'decimal
        col14.Visible = False
        Me.dgvVoucher.Columns.Add(col14)

        Dim col15 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col15.HeaderText = "业务编号"
        col15.Visible = False
        Me.dgvVoucher.Columns.Add(col15)

        Dim col16 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col16.HeaderText = "项目代码"
        col16.Visible = False
        Me.dgvVoucher.Columns.Add(col16)

        Dim col17 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col17.HeaderText = "项目名称"
        col17.Visible = False
        Me.dgvVoucher.Columns.Add(col17)

        Dim col18 As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        col18.HeaderText = "往来单位"
        col18.Visible = False
        Me.dgvVoucher.Columns.Add(col18)


        '设置行
        Me.dgvVoucher.Rows.Add(6)

        '设置行高
        'Debug.Print("当前行数：" & Me.dgvVoucher.Rows.Count & "当前列数：" &
        '            Me.dgvVoucher.Columns.GetColumnCount(0) & "显示列数：" &
        '            Me.dgvVoucher.ColumnCount & "可见列数：" &
        '            Me.dgvVoucher.Columns.GetColumnCount(DataGridViewElementStates.Visible)
        '            )
    End Sub

    ''' <summary>
    ''' 添加凭证按钮
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnAddVoucher_Click(sender As Object, e As EventArgs) Handles btnAddVoucher.Click
        '新建凭证
        '取出凭证号码
        Dim tmpMaxNumberOfVoucher As ClsTMaxNumberOfVoucher  '凭证最大号码
        'Dim tmpVoucherNumber As ClsTVoucherNumber  '

        Dim tmpMaxVoucherDb As ClsTMaxNumberOfVoucherDbAccess = New ClsTMaxNumberOfVoucherDbAccess(sysUserDataConnectionString)
        tmpMaxNumberOfVoucher = tmpMaxVoucherDb.GetVoucherMaxNumber(sysCurrentLedgerSetting.LedgerWorkYear)
        If tmpMaxNumberOfVoucher Is Nothing Then
            tmpMaxNumberOfVoucher = New ClsTMaxNumberOfVoucher()
            tmpMaxNumberOfVoucher.WorkPeriod = sysCurrentLedgerSetting.LedgerWorkYear
            tmpMaxNumberOfVoucher.VoucherNumber = 1
            tmpMaxVoucherDb.InsertVoucherMaxNumber(tmpMaxNumberOfVoucher)
        End If
        '新建凭证编号 
        m_maxVoucherId = tmpMaxNumberOfVoucher.VoucherNumber + 1
        '编辑状态修改
        m_state = 1
        m_sumOfCredit = 0D
        m_sumOfDebit = 0D
        '更新合计值
        UpdateCreditAndDebit()
        '检查控件状态
        CheckControlState()
    End Sub

    ''' <summary>
    ''' 窗体关闭
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub FrmVoucherInput_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
        If m_state <> 0 Then
            '判断是否需要保存？
            If MessageBox.Show("当前编辑需要保存吗？", "凭证处理", MessageBoxButtons.YesNo) = DialogResult.Yes Then
                e.Cancel = True
                '保存
                SaveCurVoucher()
            End If
        End If

        RemoveHandler ClsBroker.OnChange, AddressOf RecieveEmployeeChange
        RemoveHandler ClsBroker.OnChange, AddressOf RecieveVoucherGroupChange
        RemoveHandler ClsBroker.OnChange, AddressOf RecieveAccountChange
    End Sub

    ''' <summary>
    ''' 凭证类别按钮
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnVoucherGroup_Click(sender As Object, e As EventArgs) Handles btnVoucherGroup.Click
        Dim tmpFrmVoucherGroup As frmFinancialSetupVoucherType = New frmFinancialSetupVoucherType()
        tmpFrmVoucherGroup.ShowDialog()
    End Sub

    Private Sub JumpToGroup(ByVal tmpGroup As ClsTVoucherGroup)

        If m_voucherList.Count < 1 Then
            Return
        End If

        '从字典中查找
        m_curVoucherIndex = m_voucherDict(tmpGroup.ShortName & "1")
        m_curVoucher = m_voucherList(m_curVoucherIndex)
        'For Each tmpV As ClsTVoucher In m_voucherList
        '    If tmpV.VoucherGroupId = tmpGroup.GroupId Then
        '        m_curVoucher = tmpV
        '        Exit For
        '    End If
        'Next

        CheckControlState()

    End Sub


    ''' <summary>
    ''' 凭证类别下拉列表选择
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub cmbVoucherGroup_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbVoucherGroup.SelectedIndexChanged
        '取出
        Dim tmpIndex As Integer = Me.cmbVoucherGroup.SelectedIndex
        If tmpIndex = -1 Then
            Return
        End If

        Dim tmpVoucherGroup As ClsTVoucherGroup
        Dim tmpVoucherNumberDb As ClsTVoucherMaxNumberDbAccess
        Dim tmpClsVoucherNumber As ClsTVoucherNumber
        Dim tmpNewVoucherNumber As Integer

        '取出当前凭证组别对象
        tmpVoucherGroup = m_voucherGroupList.Item(tmpIndex)

        '判断当前编辑状态,如果 是浏览状态，则直接退出
        If m_state = 0 Then
            '此时要进行跳转判断，查看是否需要跳转到指定凭证
            If Not m_loading Then
                JumpToGroup(tmpVoucherGroup)
            End If
            Return
        End If
        '新增 或修改
        '根据当前选择的凭证组别填写相关信息

        '取出当前新凭证的凭证组别中的号码 
        tmpVoucherNumberDb = New ClsTVoucherMaxNumberDbAccess(sysUserDataConnectionString)
        tmpClsVoucherNumber = tmpVoucherNumberDb.GetMaxNumberByPeiodAndShortName(sysCurrentLedgerSetting.LedgerWorkYear, tmpVoucherGroup.ShortName)
        '如果不存在该组别的号码 ，则添加一条新信息到表中
        If tmpClsVoucherNumber Is Nothing Then
            '添加一个
            tmpClsVoucherNumber = New ClsTVoucherNumber()
            tmpClsVoucherNumber.VoucherNumberId = 0
            tmpClsVoucherNumber.WorkPeriod = sysCurrentLedgerSetting.LedgerWorkYear
            tmpClsVoucherNumber.GroupShortName = tmpVoucherGroup.ShortName
            tmpClsVoucherNumber.MaxNumber = 1

            tmpNewVoucherNumber = tmpVoucherNumberDb.InsertMaxNumber(tmpClsVoucherNumber)

            If tmpNewVoucherNumber = 0 Then

                tmpNewVoucherNumber = 1
            Else
                tmpClsVoucherNumber.VoucherNumberId = tmpNewVoucherNumber
            End If

            '
        Else
            tmpNewVoucherNumber = tmpClsVoucherNumber.MaxNumber + 1
        End If
        '将取得的凭证组别信息填写到相关控件中
        Me.txtVoucherNumber.Text = tmpNewVoucherNumber
        Me.txtVoucherGroupId.Text = tmpVoucherGroup.GroupId
        '这是连续凭证号码 ，每个期间都是独立的，在新建按钮点击事件中进行赋值
        '这个号码是不需要修改的
        If m_state = 1 Then
            Me.txtVoucherId.Text = m_maxVoucherId
        End If

    End Sub

    ''' <summary>
    ''' 单元格进入事件
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub dgvVoucher_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles dgvVoucher.CellEnter
        '判断当前是否处于浏览状态，
        If m_state = 0 Then
            Return
        End If
        '判断当前是哪个列
        Dim tmpCol As Integer = e.ColumnIndex
        Dim tmpValue As String
        Select Case tmpCol
            Case 0 '摘要
                '判断是否有上一行
                If e.RowIndex > 0 Then
                    tmpValue = Me.dgvVoucher.Rows(e.RowIndex - 1).Cells(tmpCol).Value
                    If tmpValue IsNot Nothing Then
                        '上一行单元格有值，则复制
                        Me.dgvVoucher.Rows(e.RowIndex).Cells(tmpCol).Value = tmpValue
                    End If
                End If
            Case 1 '科目编码
                ''如果此时科目编码已经有值，则取出对应科目，并判断辅助核算是否需要处理
                'Dim tmpAcct As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(1).Value
                ''如果此时没值，则说明是第一次填写
                'If tmpAcct Is Nothing Then
                '    Return
                'End If
                ''编码不值，则取出编码对应的科目对象
                'Dim tmpAcctCls As ClsTAccount = m_AccountList(FindAcctIndex(tmpAcct))
                'If tmpAcctCls Is Nothing Then
                '    Return
                'End If
                ''判断当前科目是否有辅助核算
                ''查看是否有辅助核算需要填写
                'If tmpAcctCls.IfRateAdjust OrElse tmpAcctCls.IfProject Then
                '    Me.groupOther.Visible = True
                '    Me.groupQuantity.Visible = False
                '    Me.groupOther.Left = Me.groupQuantity.Left
                '    Me.groupOther.Top = Me.groupQuantity.Top
                '    If tmpAcctCls.IfProject Then
                '        '项目核算
                '        Me.txtTransCode.ReadOnly = False
                '        Me.txtProjectCode.ReadOnly = False
                '        Me.txtProjectCustomer.ReadOnly = False
                '        Me.txtProjectName.ReadOnly = False
                '        '判断此时对应的单元格是否有值，如果有则填写到相应的文本框中
                '        Dim tmpTxtTransCode As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(14).Value
                '        If tmpTxtTransCode IsNot Nothing Then
                '            Me.txtTransCode.Text = tmpTxtTransCode
                '        End If
                '        Dim tmpTxtProCode As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(15).Value
                '        If tmpTxtProCode IsNot Nothing Then
                '            Me.txtProjectCode.Text = tmpTxtProCode
                '        End If
                '        Dim tmpTxtProCust As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(16).Value
                '        If tmpTxtProCust IsNot Nothing Then
                '            Me.txtProjectCustomer.Text = tmpTxtProCust
                '        End If
                '        Dim tmpTxtProName As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(17).Value
                '        If tmpTxtProName IsNot Nothing Then
                '            Me.txtProjectName.Text = tmpTxtProName
                '        End If
                '        '银行调汇
                '        Me.txtCurrency.ReadOnly = True
                '        Me.txtCurrencyCode.ReadOnly = True
                '        Me.txtCurrencyRate.ReadOnly = True
                '        '清空
                '        Me.txtCurrency.Text = ""
                '        Me.txtCurrencyCode.Text = ""
                '        Me.txtCurrencyRate.Text = ""
                '    Else
                '        '调汇
                '        Me.txtCurrency.ReadOnly = False
                '        Me.txtCurrencyCode.ReadOnly = False
                '        Me.txtCurrencyRate.ReadOnly = False
                '        '值
                '        Dim tmpCurCode As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(11).Value
                '        Dim tmpCurRate As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(12).Value
                '        Dim tmpCur As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(13).Value
                '        If tmpCurCode IsNot Nothing Then
                '            Me.txtCurrencyCode.Text = tmpCurCode
                '        End If
                '        If tmpCurRate IsNot Nothing Then
                '            Me.txtCurrencyRate.Text = tmpCurRate
                '        End If
                '        If tmpCur IsNot Nothing Then
                '            Me.txtCurrency.Text = tmpCur
                '        End If

                '        '项目核算内容
                '        Me.txtTransCode.ReadOnly = True
                '        Me.txtProjectCode.ReadOnly = True
                '        Me.txtProjectCustomer.ReadOnly = True
                '        Me.txtProjectName.ReadOnly = True
                '        '清空项目核算
                '        Me.txtTransCode.Text = ""
                '        Me.txtProjectCode.Text = ""
                '        Me.txtProjectCustomer.Text = ""
                '        Me.txtProjectName.Text = ""
                '    End If
                'Else
                '    Me.groupQuantity.Visible = True
                '    Me.groupOther.Visible = False

                '    If tmpAcctCls.IfQuantity Then
                '        '数量核算
                '        Me.txtQuantity.ReadOnly = False
                '        Me.txtPrice.ReadOnly = False
                '        '当前行的单位内容赋值
                '        Dim tmpQuan As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(5).Value
                '        Dim tmpPrice As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(6).Value
                '        'Dim tmpUnit As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(7).Value
                '        If tmpQuan IsNot Nothing Then
                '            Me.txtQuantity.Text = tmpQuan
                '        End If
                '        If tmpPrice IsNot Nothing Then
                '            Me.txtPrice.Text = tmpPrice
                '        End If
                '        'Me.dgvVoucher.Rows(e.RowIndex).Cells(7).Value = tmpAcctCls.QuantityUnit
                '    Else
                '        Me.txtQuantity.ReadOnly = True
                '        Me.txtPrice.ReadOnly = True
                '        '清空
                '        Me.txtQuantity.Text = ""
                '        Me.txtPrice.Text = ""

                '    End If
                'End If
            Case 2 '科目名称
                '是科目编码
                '取出上列
                Dim tmpCol2 As DataGridViewMultiColumnComboBoxColumn = CType(Me.dgvVoucher.Columns(1), DataGridViewMultiColumnComboBoxColumn)
                If tmpCol2 Is Nothing Then
                    Return
                End If

                Me.dgvVoucher.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = tmpCol2.SelectedValue2

                SendKeys.Send("{ENTER}")
            Case 3 '借方
            Case 4 '贷方
                '判断借方是否有数据
                tmpValue = Me.dgvVoucher.Rows(e.RowIndex).Cells(tmpCol - 1).Value
                If tmpValue Is Nothing Then
                    '借方无值
                    Me.dgvVoucher.Rows(e.RowIndex).Cells(tmpCol - 1).Value = "0.00"
                Else

                    If Decimal.Parse(tmpValue) <> 0 Then
                        Me.dgvVoucher.Rows(e.RowIndex).Cells(tmpCol).Value = "0.00"
                        SendKeys.Send("{ENTER}")
                    End If
                End If
        End Select
    End Sub

    ''' <summary>
    ''' 凭证号码内容改变事件
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub txtVoucherNumber_TextChanged(sender As Object, e As EventArgs)
        m_dirty = True
    End Sub

    ''' <summary>
    ''' 保存凭证按钮点击事件
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click

        SaveCurVoucher()

    End Sub

    Private Sub SaveCurVoucher()

        '第一步，检查控件内容合法性
        If Not ValidedControlContent() Then
            Return
        End If
        '第二步，控件内容入类对象
        ControlToClass()
        '第三步，类对象入数据库
        Dim t As Threading.Thread = New Threading.Thread(AddressOf ClassToDb)
        t.Start()

    End Sub



    ''' <summary>
    ''' 凭证线程结束后的动作
    ''' </summary>
    Private Sub VoucherSaveDone()
        '判断是否已正确保存
        If Not m_ifSaved Then
            '没有成功保存，则恢复
            '丢弃保存过渡变量
            m_presaveVoucher = Nothing
            '恢复编辑前状态
            ClassToControl()
        End If
        '恢复编辑状态
        m_state = 0
        CheckControlState()
        'CheckContentControlState()
    End Sub

    ''' <summary>
    ''' 线程保存凭证到数据库
    ''' </summary>
    Private Sub ClassToDb()
        Try

            '保存当前窗体正在编辑的类对象到数据库中
            '检查要保存的凭证对象
            If m_presaveVoucher Is Nothing Then
                '不能保存，直接返回
                Return
            End If

            '开始保存
            Dim tmpVoucherDb As ClsTVoucherDbAccess = New ClsTVoucherDbAccess(sysUserDataConnectionString)
            Dim dbAccess As ClsDbAccessMdb = tmpVoucherDb.GetConnection()
            '第一，开启事务
            dbAccess.DbOpen()
            If Not dbAccess.BeginTransaction() Then
                '开启事务失败
                MessageBox.Show("数据库事务开启失败，凭证保存失败。请重新尝试。", "凭证保存")
                Return
            End If
            '第二，保存当前凭证主体
            Dim tmpSaveRet As Integer
            If m_state = 1 Then
                tmpSaveRet = tmpVoucherDb.InsertVoucher(m_presaveVoucher)
                If tmpSaveRet <> 0 Then
                    m_presaveVoucher.VoucherAutoId = tmpSaveRet
                End If
            Else
                '编辑保存
                tmpSaveRet = tmpVoucherDb.UpdateVoucher(m_presaveVoucher)
                If tmpSaveRet = 0 Then
                    '保存失败,事务回滚
                    MessageBox.Show("凭证保存失败。请重新尝试。", "凭证保存")
                    dbAccess.RollBackTransaction()
                    Return
                    '提示退出
                End If
            End If
            '第三，保存凭证明细分录
            Dim tmpEntryDb As ClsTVoucherDetailDbAccess = New ClsTVoucherDetailDbAccess(sysUserDataConnectionString)
            Dim tmpEntryId As Integer
            If m_state = 2 Then
                '修改先删除分录
                tmpEntryDb.DeleteEntries(m_presaveVoucher.VoucherAutoId)
            End If

            For Each tmpEntry As ClsTVoucherDetail In m_presaveVoucher.EntryList
                '先修改凭证主体编号 
                tmpEntry.VoucherId = m_presaveVoucher.VoucherAutoId
                '保存
                tmpEntryId = tmpEntryDb.InsertEntry(tmpEntry)
                If tmpEntryId = 0 Then
                    '保存失败,提示退出
                    MessageBox.Show("凭证保存失败。请重新尝试。", "凭证保存")
                    dbAccess.RollBackTransaction()
                    Return
                Else
                    tmpEntry.DetailId = tmpEntryId
                End If
            Next
            '第四，提交事务
            dbAccess.CompleteTransaction()
            '第五，将保存结果存入到当前窗体凭证集合中
            If m_state = 1 Then
                '是新增
                m_voucherList.Add(m_presaveVoucher)
                m_curVoucherIndex = m_voucherList.Count - 1
                '添加到字典中
                m_voucherDict.Add(m_presaveVoucher.VoucherGroup & m_presaveVoucher.VoucherNumber, m_voucherList.Count - 1)
            End If
            '第六，修改最大凭证号
            Dim tmpMaxNumberDb As ClsTMaxNumberOfVoucherDbAccess = New ClsTMaxNumberOfVoucherDbAccess(sysUserDataConnectionString)
            If tmpMaxNumberDb.UpdateVoucherMaxNumber(m_presaveVoucher.WorkPeriod, m_presaveVoucher.VoucherId) = 0 Then
                '出错处理
            End If
            '第七，修改凭证类别凭证号
            Dim tmpGroupNumberDb As ClsTVoucherMaxNumberDbAccess = New ClsTVoucherMaxNumberDbAccess(sysUserDataConnectionString)
            If tmpGroupNumberDb.UpdateMaxNumber(m_presaveVoucher.WorkPeriod, m_presaveVoucher.VoucherGroup, m_presaveVoucher.VoucherNumber) = 0 Then
                '出错处理
            End If

            '修改当前处理凭证为保存成功的凭证
            m_curVoucher = m_presaveVoucher
            '结束保存过渡变量
            m_presaveVoucher = Nothing
            '修改当前编辑状态
            m_ifSaved = True
            '调用窗体保存后过程
            Me.Invoke(m_saveVoucherDone)
        Catch ex As Exception
            Debug.Print(ex.Message)
        End Try
    End Sub

    ''' <summary>
    ''' 表格某行变成当前行
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub dgvVoucher_RowEnter(sender As Object, e As DataGridViewCellEventArgs) Handles dgvVoucher.RowEnter
        '判断当前是否处于浏览状态，
        If m_state = 0 Then
            Return
        End If

        If e.RowIndex = -1 Then
            Return
        End If

        m_dataGridCurrentRow = e.RowIndex
        '(0) Excerpta '摘要	
        '(1) AccountCode '科目编码	
        '(2) AccountCodeName	
        '(3) Credit	
        '(4) Debit	
        '(11)Payer	此字段不使用

        '判断当前辅助核算内容是否需要填写和显示
        '(5) Quantity	'数量 'single
        '(6) Price	'单价 'decimal
        '(7) Unit	'单位 '单位
        If Me.dgvVoucher.Rows(e.RowIndex).Cells(5).Value IsNot Nothing Then
            Me.txtQuantity.Text = Me.dgvVoucher.Rows(e.RowIndex).Cells(5).Value.ToString()
            Me.txtPrice.Text = Me.dgvVoucher.Rows(e.RowIndex).Cells(6).Value.ToString()
        Else
            Me.txtQuantity.Text = ""
            Me.txtPrice.Text = ""
        End If

        '(8) SettleMode	'结算方式
        '(9) SettleCode	'结算代码
        '(10)SettleDate	'结算日期
        If Me.dgvVoucher.Rows(e.RowIndex).Cells(8).Value IsNot Nothing Then
            Me.txtSettleMode.Text = Me.dgvVoucher.Rows(e.RowIndex).Cells(8).Value.ToString()
        Else
            Me.txtSettleMode.Text = ""
        End If

        If Me.dgvVoucher.Rows(e.RowIndex).Cells(9).Value IsNot Nothing Then
            Me.txtSettleCode.Text = Me.dgvVoucher.Rows(e.RowIndex).Cells(9).Value.ToString()
        Else
            Me.txtSettleCode.Text = ""
        End If

        If Me.dgvVoucher.Rows(e.RowIndex).Cells(10).Value IsNot Nothing Then
            Me.dtpVoucherDate.Value = DateTime.Parse(Me.dgvVoucher.Rows(e.RowIndex).Cells(10).Value.ToString())

        End If

        '(11)CurrencyCode	'外币代码
        '(12)ExchangeRate	'外币汇率 'single
        '(13)CurrencyNumber	'外币数量 'decimal
        If Me.dgvVoucher.Rows(e.RowIndex).Cells(11).Value IsNot Nothing Then
            Me.txtCurrencyCode.Text = Me.dgvVoucher.Rows(e.RowIndex).Cells(11).Value.ToString()
        Else
            Me.txtCurrencyCode.Text = ""
        End If

        If Me.dgvVoucher.Rows(e.RowIndex).Cells(12).Value IsNot Nothing Then
            Me.txtCurrencyRate.Text = Me.dgvVoucher.Rows(e.RowIndex).Cells(12).Value.ToString()
        Else
            Me.txtCurrencyRate.Text = ""
        End If

        If Me.dgvVoucher.Rows(e.RowIndex).Cells(13).Value IsNot Nothing Then
            Me.txtCurrency.Text = Me.dgvVoucher.Rows(e.RowIndex).Cells(13).Value.ToString()
        Else
            Me.txtCurrency.Text = ""
        End If

        '(14)TransCode	'业务编号
        '(15)ProjectName	'项目代码
        '(16)ProjectCode	'项目名称
        '(17)ProjectCustomer	'往来单位
        If Me.dgvVoucher.Rows(e.RowIndex).Cells(14).Value IsNot Nothing Then
            Me.txtTransCode.Text = Me.dgvVoucher.Rows(e.RowIndex).Cells(14).Value.ToString()
        Else
            Me.txtTransCode.Text = ""
        End If

        If Me.dgvVoucher.Rows(e.RowIndex).Cells(15).Value IsNot Nothing Then
            Me.txtProjectName.Text = Me.dgvVoucher.Rows(e.RowIndex).Cells(15).Value.ToString()
        Else
            Me.txtProjectName.Text = ""
        End If

        If Me.dgvVoucher.Rows(e.RowIndex).Cells(16).Value IsNot Nothing Then
            Me.txtProjectCode.Text = Me.dgvVoucher.Rows(e.RowIndex).Cells(16).Value.ToString()
        Else
            Me.txtProjectCode.Text = ""
        End If

        If Me.dgvVoucher.Rows(e.RowIndex).Cells(17).Value IsNot Nothing Then
            Me.txtProjectCustomer.Text = Me.dgvVoucher.Rows(e.RowIndex).Cells(17).Value.ToString()
        Else
            Me.txtProjectCustomer.Text = ""
        End If

        '判断显示哪个组
        If Me.dgvVoucher.Rows(e.RowIndex).Cells(1).Value IsNot Nothing Then
            Dim tmpAcct As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(1).Value.ToString()
            Dim tmpAcctIndex As Integer = FindAcctIndex(Me.dgvVoucher.Rows(e.RowIndex).Cells(1).Value.ToString)

            If m_AccountList.Item(tmpAcctIndex).IfQuantity Then
                Me.groupQuantity.Visible = True
                Me.groupOther.Visible = False
            End If

            If m_AccountList.Item(tmpAcctIndex).IfProject OrElse m_AccountList.Item(tmpAcctIndex).IfRateAdjust Then
                Me.groupQuantity.Visible = False
                Me.groupOther.Visible = True
            End If

        End If
    End Sub

    ''' <summary>
    ''' 删除当前分录
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnDeleteEntry_Click(sender As Object, e As EventArgs) Handles btnDeleteEntry.Click
        '删除当前分录
        '判断当前分录是否有数据，如果有则删除当前行，如果总行数少于6则增加新行，改变当前行索引
        If ValidateRow(m_dataGridCurrentRow) Then
            Me.dgvVoucher.Rows.RemoveAt(m_dataGridCurrentRow)
            If Me.dgvVoucher.Rows.Count < 6 Then
                Me.dgvVoucher.Rows.Add()
            End If
            Me.dgvVoucher.CurrentCell = Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(0)
        End If
    End Sub

    ''' <summary>
    ''' 验证表格中一和是否有数据
    ''' </summary>
    ''' <param name="rowIndex"></param>
    ''' <returns></returns>
    Private Function ValidateRow(ByVal rowIndex As Integer) As Boolean
        '判断指定行是否包含合法数据：只要有任何一个单元格有数据即为合法
        If rowIndex > Me.dgvVoucher.Rows.Count - 1 Then
            '索引不合法
            Return False
        End If

        If Me.dgvVoucher.Rows(rowIndex).Cells(0).Value Is Nothing AndAlso
                Me.dgvVoucher.Rows(rowIndex).Cells(1).Value Is Nothing AndAlso
                Me.dgvVoucher.Rows(rowIndex).Cells(3).Value Is Nothing AndAlso
                Me.dgvVoucher.Rows(rowIndex).Cells(4).Value Is Nothing Then
            Return False
        Else
            Return True
        End If

    End Function

    ''' <summary>
    ''' 借贷金额互换
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnDebitToCredit_Click(sender As Object, e As EventArgs) Handles btnDebitToCredit.Click
        '借贷金额互换
        If m_dataGridCurrentRow = -1 Then
            Return
        End If

        Dim tmpSwap As Object
        tmpSwap = Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(3).Value
        Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(3).Value = Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(4)
        Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(4).Value = tmpSwap

    End Sub

    ''' <summary>
    ''' 根据表格当前行中分录科目编码显示当前科目余额
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnAcctBalance_Click(sender As Object, e As EventArgs) Handles btnAcctBalance.Click
        'TODO:取当前科目余额，显示在小弹窗中
    End Sub

    ''' <summary>
    ''' 单元格离开事件
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub dgvVoucher_CellLeave(sender As Object, e As DataGridViewCellEventArgs) Handles dgvVoucher.CellLeave
        '判断当前是否处于浏览状态，
        If m_state = 0 Then
            Return
        End If

        '单元格离开，判断当前单元格内容是否合乎要求，且同时要判断是否要进行合计以及大写转换
        Dim tmpCol As Integer = e.ColumnIndex
        If tmpCol = -1 Then
            Return
        End If

        '判断当前是哪个单元格
        Select Case tmpCol
            Case 0 ' 摘要
                '暂时先不进行处理
            Case 1 '科目编码
                '暂时先不进行处理
            Case 2 '科目名称
                If Me.dgvVoucher.Rows(e.RowIndex).Cells(e.ColumnIndex - 1).Value Is Nothing Then
                    Return
                End If

                '此处取出当前科目编码
                Dim tmpAcct As String = Me.dgvVoucher.Rows(e.RowIndex).Cells(e.ColumnIndex - 1).Value.ToString()
                'Dim tmpColAcct As DataGridViewMultiColumnComboBoxColumn = CType(Me.dgvVoucher.Columns.Item(e.ColumnIndex - 1), DataGridViewMultiColumnComboBoxColumn)
                Dim tmpAcctIndex As Integer = FindAcctIndex(Me.dgvVoucher.Rows(e.RowIndex).Cells(1).Value.ToString) 'tmpColAcct.SelectedIndex
                Dim tmpAcctCls As ClsTAccount = m_AccountList.Item(tmpAcctIndex)
                '查看是否有辅助核算需要填写
                If tmpAcctCls.IfRateAdjust OrElse tmpAcctCls.IfProject Then
                    Me.groupOther.Visible = True
                    Me.groupQuantity.Visible = False
                    Me.groupOther.Left = Me.groupQuantity.Left
                    Me.groupOther.Top = Me.groupQuantity.Top
                    If tmpAcctCls.IfProject Then
                        Me.txtTransCode.ReadOnly = False
                        Me.txtProjectCode.ReadOnly = False
                        Me.txtProjectCustomer.ReadOnly = False
                        Me.txtProjectName.ReadOnly = False
                    Else
                        Me.txtTransCode.ReadOnly = True
                        Me.txtProjectCode.ReadOnly = True
                        Me.txtProjectCustomer.ReadOnly = True
                        Me.txtProjectName.ReadOnly = True
                    End If
                Else
                    Me.groupQuantity.Visible = True
                    Me.groupOther.Visible = False
                    If tmpAcctCls.IfQuantity Then
                        Me.txtQuantity.ReadOnly = False
                        Me.txtPrice.ReadOnly = False
                        '当前行的单位内容赋值
                        Me.dgvVoucher.Rows(e.RowIndex).Cells(7).Value = tmpAcctCls.QuantityUnit
                    Else
                        Me.txtQuantity.ReadOnly = True
                        Me.txtPrice.ReadOnly = True
                    End If
                End If

            Case 3, 4 '借方
                '进行合计处理
                'HandleSumAndMoneyHz()
                '新线程中处理
                Dim t As Threading.Thread = New Threading.Thread(AddressOf SumAndMoney)
                t.Start()
            Case Else
                '不进行处理

        End Select
    End Sub



    ''' <summary>
    ''' 线程更新合计值及大写合计
    ''' </summary>
    Private Sub UpdateCreditAndDebit()
        Try
            '可用于多线程更新值
            Me.txtSumOfDebit.Text = m_sumOfDebit.ToString("#,###.00") '借方
            Me.txtSumOfCredit.Text = m_sumOfCredit.ToString("#,###.00") '贷方
            Me.lblMoneyHZ.Text = ConvertNumberToHz(m_sumOfCredit) '仅用贷方去转换汉字，因为保存时借贷必须相等

        Catch ex As Exception
            Debug.Print(ex.Message)
        End Try
    End Sub

    ''' <summary>
    ''' 对表格中所有行进行借贷合计
    ''' </summary>
    Private Sub SumAndMoney()
        '第一步，取出全部行，对所有行的借贷方进行合计
        Dim tmpSumOfCredit As Decimal = 0D
        Dim tmpSumOfDebit As Decimal = 0D
        Dim tmpDecimal As Decimal
        Dim tmpCol As Integer

        For tmpCol = 0 To Me.dgvVoucher.Rows.Count - 1

            Decimal.TryParse(Me.dgvVoucher.Rows(tmpCol).Cells(3).Value, tmpDecimal) '借方
            tmpSumOfDebit += tmpDecimal

            Decimal.TryParse(Me.dgvVoucher.Rows(tmpCol).Cells(4).Value, tmpDecimal) '贷方
            tmpSumOfCredit += tmpDecimal

        Next
        '第二步，用合计值进行更新
        m_sumOfCredit = tmpSumOfCredit
        m_sumOfDebit = tmpSumOfDebit

        'Debug.Print("借方：" & tmpSumOfCredit & "贷方：" & tmpSumOfDebit)
        '第三步，通知窗体更新值
        Try
            Me.Invoke(m_subUpdateSumValue)
        Catch ex As Exception
            '可能窗体已关闭了或者还没有创建
            Debug.Print("SumAndMoney" & ex.Message)
        End Try
    End Sub

    Private Sub dtpVoucherDate_KeyDown(sender As Object, e As KeyEventArgs) Handles dtpVoucherDate.KeyDown
        If e.KeyData = Keys.Enter Then
            SendKeys.Send("{Tab}")
        End If
    End Sub

    Private Sub btnDeleteVoucher_Click(sender As Object, e As EventArgs) Handles btnDeleteVoucher.Click
        '删除当前凭证
        If m_state <> 0 Then
            Return
        End If

        If m_curVoucher Is Nothing Then
            '清理显示表格
            NewContentToControl()
            Return
        End If

        If m_curVoucher.Checked Then
            MessageBox.Show("已审核凭证不能删除。", "删除凭证")
            Return
        End If

        '是否删除的提示
        If MessageBox.Show("确定要删除当前显示的凭证吗？", "删除凭证", MessageBoxButtons.YesNo) = DialogResult.No Then
            Return
        End If

        Try
            '开始事务进行删除操作
            Dim tmpVoucherDb As ClsTVoucherDbAccess = New ClsTVoucherDbAccess(sysUserDataConnectionString)
            Dim tmpDb As ClsDbAccessMdb = tmpVoucherDb.GetConnection()
            If Not tmpDb.BeginTransaction() Then
                '出错
                MessageBox.Show("开启事务失败。请重试", "删除凭证")
                Return
            End If
            '1、删除分录
            Dim tmpVdDb As ClsTVoucherDetailDbAccess = New ClsTVoucherDetailDbAccess(sysUserDataConnectionString)
            If tmpVdDb.DeleteEntries(m_curVoucher.VoucherAutoId) = 0 Then
                tmpDb.RollBackTransaction()
                MessageBox.Show("删除分录失败。请重试", "删除凭证")
                Return
            End If
            '2、删除主体
            If tmpVoucherDb.DeleteVoucher(m_curVoucher.VoucherAutoId) = 0 Then
                tmpDb.RollBackTransaction()
                MessageBox.Show("删除凭证主体失败。请重试", "删除凭证")
                Return
            End If
            '修改最大凭证号
            Dim tmpMaxNumberDb As ClsTMaxNumberOfVoucherDbAccess = New ClsTMaxNumberOfVoucherDbAccess(sysUserDataConnectionString)
            Dim tmpMaxNumCls As ClsTMaxNumberOfVoucher = tmpMaxNumberDb.GetVoucherMaxNumber(m_curVoucher.WorkPeriod)
            If tmpMaxNumCls.VoucherNumber = m_curVoucher.VoucherId Then
                If tmpMaxNumberDb.UpdateVoucherMaxNumber(tmpMaxNumCls.WorkPeriod, tmpMaxNumCls.VoucherNumber - 1) = 0 Then
                    '出错
                    tmpDb.RollBackTransaction()
                    MessageBox.Show("修改最大凭证号失败。请重试", "删除凭证")
                    Return
                End If
            End If
            Dim tmpGroupNumberDb As ClsTVoucherMaxNumberDbAccess = New ClsTVoucherMaxNumberDbAccess(sysUserDataConnectionString)
            Dim tmpGroupNumerCls As ClsTVoucherNumber = tmpGroupNumberDb.GetMaxNumberByPeiodAndShortName(m_curVoucher.WorkPeriod, m_curVoucher.VoucherGroup)
            If tmpGroupNumerCls.MaxNumber = m_curVoucher.VoucherNumber Then
                If tmpGroupNumberDb.UpdateMaxNumber(tmpGroupNumerCls.WorkPeriod, tmpGroupNumerCls.GroupShortName, tmpGroupNumerCls.MaxNumber - 1) = 0 Then
                    '出错
                    tmpDb.RollBackTransaction()
                    MessageBox.Show("修改凭证组最大凭证号失败。请重试", "删除凭证")
                    Return
                End If
            End If
            '提交事务
            If Not tmpDb.CompleteTransaction() Then
                '出错，回滚
                tmpDb.RollBackTransaction()
                MessageBox.Show("提交事务失败。请重试", "删除凭证")
                Return
            End If
            '3、通知删除消息
            Dim m_broke As ClsBroker = New ClsBroker()
            Dim be As TransEventArg = New TransEventArg()
            be.Msg = "DeleteVoucher"
            be.Obj = m_curVoucher
            m_broke.BroadCastEvent(be)


            '4、从集合中移除
            m_voucherList.Remove(m_curVoucher)
            '从字典中移除
            m_voucherDict.Remove(m_curVoucher.VoucherGroup & m_curVoucher.VoucherNumber)

            '5、修改当前凭证
            If m_voucherList.Count > 0 Then
                '向下移动
                If m_curVoucherIndex >= m_voucherList.Count Then
                    m_curVoucherIndex = m_voucherList.Count - 1
                End If
                m_curVoucher = m_voucherList.Item(m_curVoucherIndex)
            Else
                m_curVoucherIndex = -1
                m_curVoucher = Nothing
            End If
            '6、修改当前显示凭证
            ClassToControl()
            CheckControlState()
        Catch ex As Exception
            Debug.Print(ex.Message)
        End Try
    End Sub

    Private Sub btnNext_Click(sender As Object, e As EventArgs) Handles btnNext.Click
        '移到下一个凭证
        If m_state <> 0 Then
            btnNext.Enabled = False
            Return
        End If

        m_curVoucherIndex += 1

        MoveVoucherPointer()

        CheckControlState()
    End Sub

    Private Sub MoveVoucherPointer()

        If m_voucherList.Count < 1 Then
            m_curVoucherIndex = -1
            m_curVoucher = Nothing

            NewContentToControl()
        Else

            If m_curVoucherIndex >= m_voucherList.Count Then
                m_curVoucherIndex = m_voucherList.Count - 1
            ElseIf m_curVoucherIndex < 0 Then
                m_curVoucherIndex = 0
            End If

            '移动到指定凭证
            m_curVoucher = m_voucherList.Item(m_curVoucherIndex)

        End If

    End Sub

    Private Sub btnLast_Click(sender As Object, e As EventArgs) Handles btnLast.Click
        '移到最后一个凭证
        If m_state <> 0 Then
            btnLast.Enabled = False
            Return
        End If

        If m_voucherList.Count > 0 Then
            m_curVoucherIndex = m_voucherList.Count - 1
        End If

        MoveVoucherPointer()

        CheckControlState()
    End Sub

    Private Sub btnPrev_Click(sender As Object, e As EventArgs) Handles btnPrev.Click
        If m_state <> 0 Then
            btnPrev.Enabled = False
            Return
        End If


        m_curVoucherIndex -= 1

        MoveVoucherPointer()

        CheckControlState()
    End Sub

    Private Sub btnFirst_Click(sender As Object, e As EventArgs) Handles btnFirst.Click
        If m_state <> 0 Then
            btnFirst.Enabled = False
            Return
        End If

        If m_voucherList.Count > 0 Then
            m_curVoucherIndex = 0
        End If

        MoveVoucherPointer()

        CheckControlState()
    End Sub

    Private Sub btnFindAcct_Click(sender As Object, e As EventArgs) Handles btnFindAcct.Click
        '查找科目
        If m_state = 0 Then
            btnFindAcct.Enabled = False
            Return
        End If

        '查找科目
        ShowFindAcctWindow()

    End Sub


    Private Sub btnFindVoucher_Click(sender As Object, e As EventArgs) Handles btnFindVoucher.Click
        '查找凭证
        'TODO:此处弹出查找凭证窗体
    End Sub

    Private Sub btnModifyVoucher_Click(sender As Object, e As EventArgs) Handles btnModifyVoucher.Click
        '编辑当前显示的凭证
        If m_curVoucher Is Nothing Then
            Return
        End If
        m_state = 2
        CheckControlState()
    End Sub

    'Private Sub btnClose_Click(sender As Object, e As EventArgs) Handles btnClose.Click
    '    '关闭
    '    If m_state <> 0 Then
    '        '判断是否需要保存？
    '        If MessageBox.Show("当前编辑需要保存吗？", "凭证处理", MessageBoxButtons.YesNo) = DialogResult.No Then
    '            Me.Close()
    '        Else
    '            '保存
    '            SaveCurVoucher()
    '        End If
    '    Else
    '        Me.Close()
    '    End If
    'End Sub

    Private Sub btnAcctSetup_Click(sender As Object, e As EventArgs) Handles btnAcctSetup.Click
        '科目设置
        Dim tmpForm As Form = GenericSingleton(Of frmFinancialSetupAcct).CreateInstance()
        If tmpForm IsNot Nothing Then
            With tmpForm
                .MdiParent = sysFrmMdiMain
                .StartPosition = FormStartPosition.CenterScreen
                .Show()
            End With
        End If
    End Sub


    Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
        '取消修改
        If m_state = 0 Then
            Return
        End If

        If MessageBox.Show("确定要放弃当前的编辑？", "编辑凭证", MessageBoxButtons.YesNo) = DialogResult.Yes Then

            m_state = 0
            m_dirty = False
            m_saving = False

            CheckControlState()

        End If


    End Sub

    '打印预览对话框
    Private m_printpreviewDlg As PrintPreviewDialog
    Private m_voucherDocument As VoucherPrintDocument
    '页面设置
    Private m_voucherPaper As Printing.PageSettings

    Private Sub btnPreview_Click(sender As Object, e As EventArgs) Handles btnPreview.Click

        If m_curVoucher Is Nothing Then
            Return
        End If

        Dim printList As List(Of ClsTVoucher) = New List(Of ClsTVoucher)()
        printList.Add(m_curVoucher）


        m_voucherDocument = New VoucherPrintDocument()
        m_voucherDocument.VoucherList = printList

        m_voucherDocument.CompanyName = sysCurrentLedgerSetting.CompanyName
        Dim printDoc As Printing.PrintDocument = m_voucherDocument.PrintVoucher()

        m_printpreviewDlg = New PrintPreviewDialog()
        m_printpreviewDlg.Document = printDoc

        '定义新按钮
        '打印对话框
        Dim btnPrintDlg As ToolStripButton = New ToolStripButton()
        btnPrintDlg.Image = My.Resources.PRINT  'Image.FromFile(IO.Path.Combine(IO.Path.Combine(IO.Path.Combine(sysAppCurrentPath, "pic"), "bmp32"), "print.bmp"))
        btnPrintDlg.DisplayStyle = ToolStripItemDisplayStyle.Image
        btnPrintDlg.ToolTipText = "设置打印机并打印"
        AddHandler btnPrintDlg.Click, AddressOf OpenPrintDlg

        '打印纸张设置
        Dim btnPaperDlg As ToolStripButton = New ToolStripButton()
        btnPaperDlg.Image = My.Resources.paperSetup  'Image.FromFile(IO.Path.Combine(IO.Path.Combine(IO.Path.Combine(sysAppCurrentPath, "pic"), "bmp32"), "new.bmp"))
        btnPaperDlg.DisplayStyle = ToolStripItemDisplayStyle.Image
        btnPaperDlg.ToolTipText = "页面设置"
        AddHandler btnPaperDlg.Click, AddressOf OpenPagerSettingDlg

        Dim newToolStrip As ToolStrip = Nothing
        '查找printpreviwDialog窗体中的打印按钮
        For Each c As Control In m_printpreviewDlg.Controls
            If TypeName(c) = "ToolStrip" Then
                newToolStrip = c
                Exit For
            End If
        Next
        If newToolStrip IsNot Nothing Then
            '替换打印按钮
            newToolStrip.Items.RemoveAt(0) '打印按钮是第一个
            newToolStrip.Items.Insert(0, btnPrintDlg)

            newToolStrip.Items.Insert(1, btnPaperDlg)
        End If

        m_printpreviewDlg.ShowDialog()

    End Sub

    Private Sub OpenPagerSettingDlg(sender As Object, e As EventArgs)
        Dim paperDlg As PageSetupDialog = New PageSetupDialog()

        paperDlg.Document = m_printpreviewDlg.Document

        If My.Settings.VoucherPageSettings IsNot Nothing Then
            paperDlg.PageSettings = My.Settings.VoucherPageSettings
        Else
            paperDlg.PageSettings = m_printpreviewDlg.Document.DefaultPageSettings
        End If

        paperDlg.PrinterSettings = New System.Drawing.Printing.PrinterSettings

        If paperDlg.ShowDialog() = DialogResult.OK Then
            m_printpreviewDlg.Document.DefaultPageSettings = paperDlg.PageSettings
            '同时保存到配置文件中
            My.Settings.VoucherPageSettings = paperDlg.PageSettings

            m_printpreviewDlg.PrintPreviewControl.InvalidatePreview()

        End If
    End Sub

    Private Sub OpenPrintDlg(sender As Object, e As EventArgs)
        Dim pD As PrintDialog = New PrintDialog()
        pD.Document = m_printpreviewDlg.Document

        If pD.ShowDialog = DialogResult.OK Then
            m_printpreviewDlg.Document.PrinterSettings = pD.PrinterSettings
            m_printpreviewDlg.Document.Print()
            'pD.Document.Print()

        End If
    End Sub

    Private Sub btnPrint_Click(sender As Object, e As EventArgs) Handles btnPrint.Click

        m_voucherDocument = New VoucherPrintDocument()
        m_voucherDocument.VoucherList = m_voucherList
        m_voucherDocument.CompanyName = sysCurrentLedgerSetting.CompanyName
        Dim printDoc As Printing.PrintDocument = m_voucherDocument.PrintVoucher()

        m_printpreviewDlg = New PrintPreviewDialog()
        m_printpreviewDlg.Document = printDoc

        '定义新按钮
        '打印对话框
        Dim btnPrintDlg As ToolStripButton = New ToolStripButton()
        btnPrintDlg.Image = My.Resources.PRINT  'Image.FromFile(IO.Path.Combine(IO.Path.Combine(IO.Path.Combine(sysAppCurrentPath, "pic"), "bmp32"), "print.bmp"))
        btnPrintDlg.DisplayStyle = ToolStripItemDisplayStyle.Image
        btnPrintDlg.ToolTipText = "设置打印机并打印"
        AddHandler btnPrintDlg.Click, AddressOf OpenPrintDlg

        '打印纸张设置
        Dim btnPaperDlg As ToolStripButton = New ToolStripButton()
        btnPaperDlg.Image = My.Resources.paperSetup  'Image.FromFile(IO.Path.Combine(IO.Path.Combine(IO.Path.Combine(sysAppCurrentPath, "pic"), "bmp32"), "new.bmp"))
        btnPaperDlg.DisplayStyle = ToolStripItemDisplayStyle.Image
        btnPaperDlg.ToolTipText = "页面设置"
        AddHandler btnPaperDlg.Click, AddressOf OpenPagerSettingDlg

        Dim newToolStrip As ToolStrip = Nothing
        '查找printpreviwDialog窗体中的打印按钮
        For Each c As Control In m_printpreviewDlg.Controls
            If TypeName(c) = "ToolStrip" Then
                newToolStrip = c
                Exit For
            End If
        Next
        If newToolStrip IsNot Nothing Then
            '替换打印按钮
            newToolStrip.Items.RemoveAt(0) '打印按钮是第一个
            newToolStrip.Items.Insert(0, btnPrintDlg)

            newToolStrip.Items.Insert(1, btnPaperDlg)
        End If

        m_printpreviewDlg.ShowDialog()

    End Sub

    Private Sub btnCopyVoucher_Click(sender As Object, e As EventArgs) Handles btnCopyVoucher.Click
        'TODO:复制凭证
    End Sub

    Private Sub btnEmployee_Click(sender As Object, e As EventArgs) Handles btnEmployee.Click
        'TODO:员工管理
    End Sub

    Private Sub btnPaperSetup_Click(sender As Object, e As EventArgs) Handles btnPaperSetup.Click
        Dim paperDlg As PageSetupDialog = New PageSetupDialog()

        '纸张设置
        If My.Settings.VoucherPageSettings IsNot Nothing Then
            paperDlg.PageSettings = My.Settings.VoucherPageSettings
        Else
            paperDlg.PageSettings = New Printing.PageSettings()
        End If

        '打印机设置
        paperDlg.PrinterSettings = New System.Drawing.Printing.PrinterSettings

        '显示对话框
        If paperDlg.ShowDialog() = DialogResult.OK Then

            '保存到窗体变量中
            If m_voucherPaper Is Nothing Then
                m_voucherPaper = New Printing.PageSettings()
            End If

            m_voucherPaper = paperDlg.PageSettings
            '保存到程序配置文件中
            My.Settings.VoucherPageSettings = paperDlg.PageSettings
        End If
    End Sub

    Private Sub btnCheck_Click(sender As Object, e As EventArgs) Handles btnCheck.Click

        '判断当前是否允许审核与制单人相同
        If Not sysCurrentLedgerSetting.IfSelfCheckVoucher Then
            '不允许同一人制单并审核
            '判断当前制单人与审核人是否相同
            If m_curVoucher.Maker.Equals(sysCurrentClsUser.UserName) Then
                MessageBox.Show("审核与制单不能是同一个人。", "审核凭证")
                Return
            End If
        End If

        '审核或消审当前凭证
        If m_curVoucher.Checked Then
            m_curVoucher.Checked = False
            m_curVoucher.Checker = ""
        Else
            m_curVoucher.Checked = True
            m_curVoucher.Checker = sysCurrentClsUser.UserName
        End If

        '写入数据库
        Dim tmpList As List(Of ClsTVoucher) = New List(Of ClsTVoucher)()
        tmpList.Add(m_curVoucher)

        If SaveVoucherList(tmpList, 0, m_curVoucher.Checked) = 0 Then
            '出错
        End If

        CheckControlState()

    End Sub


    ''' <summary>
    ''' 用于批量保存凭证信息，比如审核、过账信息
    ''' </summary>
    ''' <param name="tmpList">凭证列表集合</param>
    ''' <param name="which">过账或审核：0- 审核，1-过账，其他非法</param>
    ''' <param name="value"></param>
    ''' <returns></returns>
    Private Function SaveVoucherList(tmpList As List(Of ClsTVoucher), ByVal which As Int16, ByVal value As Boolean) As Integer
        '
        If tmpList Is Nothing Then
            Return 0
        End If

        Dim tmpVoucherDb As ClsTVoucherDbAccess = New ClsTVoucherDbAccess(sysUserDataConnectionString)
        Dim tmpRetInt As Integer

        If which = 0 Then
            tmpRetInt = tmpVoucherDb.CheckVoucher(tmpList, value)
        Else
            tmpRetInt = tmpVoucherDb.PostVoucher(tmpList, value)
        End If

        Return tmpRetInt

    End Function

    Private Sub btnCheckAll_Click(sender As Object, e As EventArgs) Handles btnCheckAll.Click
        '审核 全部凭证
        '判断当前是否允许审核与制单人相同
        If Not sysCurrentLedgerSetting.IfSelfCheckVoucher Then
            '不允许同一人制单并审核
            '判断当前制单人与审核人是否相同
            If m_curVoucher.Maker.Equals(sysCurrentClsUser.UserName) Then
                MessageBox.Show("审核与制单不能是同一个人。", "审核凭证")
                Return
            End If
        End If

        For Each tmpV As ClsTVoucher In m_voucherList
            tmpV.Checked = True
            tmpV.Checker = sysCurrentClsUser.UserName
        Next

        '写入数据库
        If SaveVoucherList(m_voucherList, 0, True) = 0 Then
            '出错
        End If

        CheckControlState()

    End Sub

    Private Sub btnUnCheckAll_Click(sender As Object, e As EventArgs) Handles btnUnCheckAll.Click
        '全部消审 
        '判断当前是否允许审核与制单人相同
        If Not sysCurrentLedgerSetting.IfSelfCheckVoucher Then
            '不允许同一人制单并审核
            '判断当前制单人与审核人是否相同
            If m_curVoucher.Maker.Equals(sysCurrentClsUser.UserName) Then
                MessageBox.Show("审核与制单不能是同一个人。", "审核凭证")
                Return
            End If
        End If

        For Each tmpV As ClsTVoucher In m_voucherList
            tmpV.Checked = False
            tmpV.Checker = ""
        Next

        '写入数据库
        If SaveVoucherList(m_voucherList, 0, False) = 0 Then
            '出错
        End If

        CheckControlState()

    End Sub

    Private Sub txtPrice_Leave(sender As Object, e As EventArgs) Handles txtPrice.Leave
        '数量单价
        If String.IsNullOrEmpty(Me.txtPrice.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(6).Value = Me.txtPrice.Text.Trim()
        End If
    End Sub

    Private Sub txtQuantity_Leave(sender As Object, e As EventArgs) Handles txtQuantity.Leave
        '数量
        If String.IsNullOrEmpty(Me.txtQuantity.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(5).Value = Me.txtQuantity.Text.Trim()
        End If
    End Sub

    Private Sub txtSettleCode_Leave(sender As Object, e As EventArgs) Handles txtSettleCode.Leave
        '结算代码
        If String.IsNullOrEmpty(Me.txtSettleCode.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(9).Value = Me.txtSettleCode.Text.Trim()
        End If
    End Sub

    Private Sub txtSettleMode_Leave(sender As Object, e As EventArgs) Handles txtSettleMode.Leave
        '结算方式
        If String.IsNullOrEmpty(Me.txtSettleMode.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(8).Value = Me.txtSettleMode.Text.Trim()
        End If
    End Sub

    Private Sub dtpSettleDate_LostFocus(sender As Object, e As EventArgs) Handles dtpSettleDate.LostFocus
        '结算日期
        If Not String.IsNullOrEmpty(Me.txtSettleMode.Text) OrElse Not String.IsNullOrEmpty(Me.txtSettleCode.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(10).Value = Me.dtpSettleDate.Value.ToShortDateString
        End If
    End Sub

    Private Sub txtCurrency_Leave(sender As Object, e As EventArgs) Handles txtCurrency.Leave
        '外币数量
        If String.IsNullOrEmpty(Me.txtCurrency.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(13).Value = Me.txtCurrency.Text.Trim()
        End If
    End Sub

    Private Sub txtCurrencyCode_Leave(sender As Object, e As EventArgs) Handles txtCurrencyCode.Leave
        '外币代码
        If String.IsNullOrEmpty(Me.txtCurrencyCode.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(11).Value = Me.txtCurrencyCode.Text.Trim()
        End If
    End Sub

    Private Sub txtCurrencyRate_Leave(sender As Object, e As EventArgs) Handles txtCurrencyRate.Leave
        '外币汇率
        If String.IsNullOrEmpty(Me.txtCurrencyRate.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(12).Value = Me.txtCurrencyRate.Text.Trim()
        End If
    End Sub

    Private Sub txtTransCode_Leave(sender As Object, e As EventArgs) Handles txtTransCode.Leave
        '项目业务编号
        If String.IsNullOrEmpty(Me.txtTransCode.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(14).Value = Me.txtTransCode.Text.Trim()
        End If
    End Sub

    Private Sub txtProjectCode_Leave(sender As Object, e As EventArgs) Handles txtProjectCode.Leave
        '项目编码
        If String.IsNullOrEmpty(Me.txtProjectCode.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(15).Value = Me.txtProjectCode.Text.Trim()
        End If
    End Sub

    Private Sub txtProjectName_Leave(sender As Object, e As EventArgs) Handles txtProjectName.Leave
        '项目名称
        If String.IsNullOrEmpty(Me.txtProjectName.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(16).Value = Me.txtProjectName.Text.Trim()
        End If
    End Sub

    Private Sub txtProjectCustomer_Leave(sender As Object, e As EventArgs) Handles txtProjectCustomer.Leave
        '往来单位
        If String.IsNullOrEmpty(Me.txtProjectCustomer.Text) Then
            Me.dgvVoucher.Rows(m_dataGridCurrentRow).Cells(17).Value = Me.txtProjectCustomer.Text.Trim()
        End If
    End Sub

    Private Sub txtVoucherNumber_TextChanged_1(sender As Object, e As EventArgs) Handles txtVoucherNumber.TextChanged
        If m_state <> 0 Then
            Return
        End If

        Dim tmpNum As Integer
        Integer.TryParse(Me.txtVoucherNumber.Text.Trim(), tmpNum)

        If tmpNum = 0 Then
            Return
        End If

        Dim tmpGroup As ClsTVoucherGroup
        If cmbVoucherGroup.SelectedIndex = -1 Then
            tmpGroup = m_voucherGroupList(0) '.GroupId
        Else
            tmpGroup = m_voucherGroupList(cmbVoucherGroup.SelectedIndex) '.GroupId
        End If

        '从字典中查找
        If m_voucherDict.ContainsKey(tmpGroup.ShortName & tmpNum) Then
            m_curVoucherIndex = m_voucherDict(tmpGroup.ShortName & tmpNum)
            'MoveVoucherPointer()             '
            m_curVoucher = m_voucherList(m_curVoucherIndex)
            CheckControlState()
        End If

    End Sub

    Private Sub FrmVoucherInput_ClientSizeChanged(sender As Object, e As EventArgs) Handles Me.ClientSizeChanged

    End Sub
End Class